﻿using System;
using System.Collections;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc.Controllers;
using Microsoft.AspNetCore.Mvc.Filters;
using Microsoft.Extensions.DependencyInjection;
using RAP.Framework.Libary.Lock;
using RAP.Framework.Libary.Utils;
using RAP.Web.Libary.Common;
using RAP.Web.Libary.Common.Model;
using RAP.Web.Libary.Service.Session;
using static RAP.Web.Libary.Common.FieldConsts;

namespace RAP.Web.Libary.Controller.Attributes
{
  /// <summary>
  /// 标记Controller或Action是否需要会话，默认不需要
  /// </summary>
  public class NeedSessionAttribute : Attribute
  {
    private static IDictionary<string, NeedSessionAttribute> _needSessionActions = new ConcurrentDictionary<string, NeedSessionAttribute>();

    /// <summary>
    /// 是否需要回话，如果需要，则将会话注入查询参数；如果不存在会话则忽略
    /// </summary>
    public bool IsNeedSession { get; set; } = true;

    /// <summary>
    /// 用户回话是否是必须的，如果是必须的且当前无回话，则会返回会话无效（100000）错误
    /// </summary>
    public bool IsRequired { get; set; } = true;

    /// <summary>
    /// 
    /// </summary>
    /// <param name="context"></param>
    /// <returns></returns>
    public async static Task<bool> ProcessAttributes(ActionExecutingContext context)
    {
      var actionMethod = (context.ActionDescriptor as ControllerActionDescriptor).MethodInfo;
      var actionKey = $"{actionMethod.DeclaringType.FullName}.{actionMethod.Name}";
      var controller = context.Controller as IWebController;
      if (!_needSessionActions.TryGetValue(actionKey, out var needSessionAttr))
      {
        GlobalLocks.Lock(actionKey, () =>
        {
          return _needSessionActions.TryGetValue(actionKey, out needSessionAttr);
        }, () =>
        {
          //如果缓存中未找到当前Action的NeedSessionAttribute定义，则尝试查找NeedSessionAttribute定义并缓存
          needSessionAttr = actionMethod.GetCustomAttributes<NeedSessionAttribute>().FirstItem();
          if (needSessionAttr == null)
          {
            needSessionAttr = controller.GetType().GetCustomAttributes<NeedSessionAttribute>().FirstItem();
          }
          _needSessionActions.TryAdd(actionKey, needSessionAttr);
        });
      }
      if (needSessionAttr == null)
      {
        //如果Action或Action所属Class不存在NeedSessionAttribute定义，则直接返回true
        return true;
      }
      var isNeedSession = needSessionAttr.IsNeedSession;
      var isRequired = needSessionAttr.IsRequired;
      var queryParams = controller.QueryParams as IAPIQueryParams;
      var userInfoService = context.HttpContext.RequestServices.GetService<IUserInfoService>();
      var session = await userInfoService.GetUserSession(queryParams);
      if (isRequired && session == null)
      {
        //如果必须会话存在，那么返回false
        return false;
      }
      if (isNeedSession && session!= null)
      {
        //如果需要会话，则将会话信息注入QueryParams对象中
        queryParams.UserSession = session;
      }
      return true;
    }
  }
}
